package com.team.game.Game.MapHelper;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Region;
import android.view.MotionEvent;

import com.team.game.Assets;
import com.team.game.Screens.Upgrade_Screen;
import com.team.game.framework.Game;
import com.team.game.framework.impl.MainActivity;
import com.team.game.framework.impl.Scale_X_Y;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import static com.team.game.framework.impl.Scale_X_Y.Scale_X;
import static com.team.game.framework.impl.Scale_X_Y.Scale_Y;
import static com.team.game.framework.impl.Scale_X_Y.Size_X;
import static com.team.game.framework.impl.Scale_X_Y.Size_Y;

public class Map {
    private Game game;

    private final float x = Scale_X_Y.Scale_X;
    private final float y = Scale_X_Y.Scale_Y;
    private final float maxX = (Size_X) * (-2),   //максимальная позиция
            maxY = (Size_Y) * (-1);   //только если карта 3x2 экрана

    private Bitmap fullmap;
    private Matrix fullmapMatrix;

    private ArrayList<Region> region;

    private float[] v = new float[9];  //для сохранения параметров матрицы

    public final Border border;

    private int unlockLocation;

//
//    float[] src = {(219*x), (1306*y), (1202*x), (1875*y)};
//
//    float[] dst = {(321*x), (420*y), ( 935*x), (1496*y)};

    public Map (Game game) {
        this.game = game;

        unlockLocation = game.getDatabase().getUnlockLocation();
        region = new ArrayList<> (unlockLocation);

        initPath (region, unlockLocation);

        fullmapMatrix = new Matrix ();
        fullmapMatrix.preTranslate (0, 0);

        border = new Border (game, 0);

        InputStream inputStream;
        try {
            inputStream = MainActivity.manager.open ("Picture/fullmap.jpg");
            fullmap = Bitmap.createScaledBitmap (BitmapFactory.decodeStream (inputStream), (int) (3240 * Scale_X), (int) (3840 * Scale_Y), false);
        } catch (IOException e) {
            e.printStackTrace ();
        }

    }

    public void update () {
        fullmapMatrix.getValues (v);

        realX = v[Matrix.MTRANS_X];
        //реальная позиция матрицы
        realY = v[Matrix.MTRANS_Y];

        //чтобы не выйти за рамки карты
        if (realX + scrollX > 0 || realX + scrollX < maxX)
            scrollX = 0;
        if (realY + scrollY > 0 || realY + scrollY < maxY)
            scrollY = 0;

        int bufX = (int) scrollX;
        int bufY = (int) scrollY;
        fullmapMatrix.preTranslate (bufX, bufY);

        for (int i = 0; i < unlockLocation; i++) {
            region.get(i).translate(bufX, bufY);
        }

        border.update ();
    }

    public void present (Canvas canvas) {
        canvas.drawRGB (181, 195, 204);
        canvas.drawBitmap (fullmap, fullmapMatrix, null);
        border.present (canvas);
    }

    private float angle = 0; //угол поворота локации относительно 0,0
    private float scale = 0; //на сколько увеличить изображение
    private PointF point = new PointF (); //конечная точка матрицы после трансформации

    private void rotateMoveScale (int loc) {
        switch (loc){
            case 1:
                angle = 30.00f;
                scale = 0.2f; //1...1.2
                point.set (820 * Scale_Y, -759 * Scale_X);

                //825, -650 для обычного
                //624, -544 для моего
                //если разделить эти значения то получится что скейлы должны быть наоборот
                //почему - хз
                //но все работает
        }

    }

    private int i = 0;

    public boolean animate () {
        if (i < 32) {
            //TODO Скейлы
            fullmapMatrix.preRotate (angle / 32);

            float x1 = point.x - v[Matrix.MTRANS_X];
            float y1 = point.y - v[Matrix.MTRANS_Y];

            //fullmapMatrix.preScale (1.0015f, 1.0015f);
            fullmapMatrix.postTranslate (x1 / 32, y1 / 32);

            i++;
            border.update ();
            return false;
        } else {
            i = 0 ;
            return true;
        }
    }

    //TODO Дописать по аналогии с анимейт
    public boolean unroll () {
        if (i < 32) {

            //fullmapMatrix.preScale (0.9985f, 0.0085f);
            fullmapMatrix.preRotate (angle / -32);

            float x = v[Matrix.MTRANS_X] - point.x;
            float y = v[Matrix.MTRANS_Y] - point.y;

            fullmapMatrix.postTranslate (x / 32, y / 32);

            i++;
            border.update ();

            return false;
        } else {
            i = 0;
            return true;
        }
    }

    public void restore (){
        fullmapMatrix.reset ();
        i = 0;
    }


    private int isBorderInt = 0, isLocation = 0;

    private float downX = 0, downY = 0;
    private float scrollX = 0, scrollY = 0;
    private float realX = 0, realY = 0;
    private float currentX = 0, currentY = 0;
    private float downDownX = 0, downDownY = 0;

    public int OnScroll (MotionEvent event) {
        switch (event.getAction ()) {
            case MotionEvent.ACTION_DOWN:
                isBorderInt = border.touch(event);
                if( isBorderInt == 0)
                {
                    downDownX = downX = event.getX ();
                    downDownY = downY = event.getY ();
                    isLocation = this.check(downX,downY);
                }
                //первое касание
                break;
            case MotionEvent.ACTION_MOVE:
                if( isBorderInt == 0) {
                    currentX = event.getX();
                    currentY = event.getY();
                    //расчитуем на сколько нужно проскролить
                    scrollX = (int) ((currentX - downX) * 0.75f);
                    scrollY = (int) ((currentY - downY) * 0.75f);

                    downX = currentX;
                    downY = currentY;
                }
                break;
            case MotionEvent.ACTION_UP: {
                if (isBorderInt == 0) {
                    currentX = event.getX();
                    currentY = event.getY();
                    //немного уменьшаем для плавности

                    scrollX = (int) ((currentX - downX) * 0.75f);
                    scrollY = (int) ((currentY - downY) * 0.75f);

                    if (isLocation != 0) {
                        if (this.fivePixelValidation(downDownX, downDownY, currentX, currentY)) {
                            if (isLocation == this.check(currentX, currentY)) {
                                this.rotateMoveScale(isLocation);

                                return isLocation;
                            }
                        }
                    } else {
                        return 0;
                    }
                } else {
                    if (isBorderInt == border.touch(event)) {
                        this.setReguestedScreen(isBorderInt);
                    }
                }
            }

        }
        return 0;
    }

    private int check (float x, float y){
        for (int i = 0 ; i < unlockLocation; i++)
            if (region.get (i).contains ((int) (x), (int) (y))) {
                return i + 1;
            }
        return 0;
    }

    public void setReguestedScreen(int check){
        switch (check){
            case 1:
                break;
            case 2:
                break;
            case 3:
                game.setScreen (new Upgrade_Screen (game));
                break;
            case 4:
                break;
        }
    }

    private RectF tenPixelRectf = new RectF ();

    private boolean fivePixelValidation (float x, float y, float x1, float y1) {
        tenPixelRectf.set (x - 5 * Scale_X, y - 5 * Scale_Y, x + 5 * Scale_X, y + 5 * Scale_Y);

        return Assets.inRect (tenPixelRectf, x1, y1);
    }

    //TODO Вынести в отдельный класс
    private void initPath (ArrayList<Region> region, int unlockLocation) {
        Path path = new Path ();
        for(int i = 0; i < unlockLocation; i ++) {
            region.add (i, new Region ());
            switch (i) {
                case 0: {
                    path.moveTo(651 * x, 1237 * y);
                    path.cubicTo(798 * x, 1126 * y, 982 * x, 1308 * y, 918 * x, 1376 * y);
                    path.cubicTo(1120 * x, 1498 * y, 1025 * x, 1546 * y, 917 * x, 1541 * y);
                    path.cubicTo(589 * x, 1664 * y, 886 * x, 1795 * y, 945 * x, 1718 * y);
                    path.cubicTo(969 * x, 1755 * y, 1068 * x, 1750 * y, 1031 * x, 1860 * y);
                    path.cubicTo(1127 * x, 1890 * y, 1159 * x, 2035 * y, 1037 * x, 2108 * y);
                    path.cubicTo(922 * x, 1941 * y, 1004 * x, 2233 * y, 791 * x, 2033 * y);
                    path.cubicTo(728 * x, 1815 * y, 678 * x, 2194 * y, 420 * x, 1843 * y);
                    path.cubicTo(468 * x, 2033 * y, 323 * x, 1918 * y, 340 * x, 1839 * y);
                    path.cubicTo(112 * x, 1851 * y, 300 * x, 1682 * y, 86 * x, 1537 * y);
                    path.lineTo(161 * x, 1459 * y);
                    path.cubicTo(283 * x, 1530 * y, 142 * x, 1267 * y, 295 * x, 1337 * y);
                    path.quadTo(328 * x, 1191 * y, 429 * x, 1213 * y);
                    path.cubicTo(469 * x, 1095 * y, 569 * x, 1078 * y, 651 * x, 1237 * y);
                    path.close();
                    region.get (i).setPath (path, new Region (0, 0, Size_X * 3, Size_Y * 2));
                    break;
                }
                case 1: {

                    break;
                }
            }
        }
    }
}
